package user

import (
	"context"
	"gitee.com/g-qs/gin-vue-admin/server/global"
	"gitee.com/g-qs/gin-vue-admin/server/model/common/response"
	"gitee.com/g-qs/gin-vue-admin/server/model/system"
	"gitee.com/g-qs/gin-vue-admin/server/model/system/request"
	"gitee.com/g-qs/gin-vue-admin/server/model/user"
	userReq "gitee.com/g-qs/gin-vue-admin/server/model/user/request"
	userRes "gitee.com/g-qs/gin-vue-admin/server/model/user/response"
	"gitee.com/g-qs/gin-vue-admin/server/utils"
	"github.com/gin-gonic/gin"
	"github.com/gofrs/uuid/v5"
	"github.com/redis/go-redis/v9"
	"go.uber.org/zap"
	"strconv"
)

type BaseApi struct {
}

// SignUp 注册
// @Tags User
// @Summary 注册
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body user.SignUp true "注册"
// @Success 200 {string} string "{"code":0,"data":{},"msg":"注册成功"}"
// @Router /api/user/signUp [post]
func (b *BaseApi) SignUp(c *gin.Context) {
	var r userReq.Register
	err := c.ShouldBindJSON(&r)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	err = utils.Verify(r, utils.UserSignUpVerify)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	// 判断手机号是否已存在
	phone, _ := UserService.FindUserByWhere(map[string]interface{}{"phone": r.Phone}, "id")
	if phone.ID != 0 {
		response.Result(7, "", "该号码已注册,请登录!", c)
		return
	}
	uuid, _ := uuid.NewV4()
	userData := &user.User{
		GVA_MODEL: global.GVA_MODEL{},
		UUID:      uuid,
		Phone:     r.Phone,
		Password:  r.Password,
		Name:      "fdNick_" + r.Phone[len(r.Phone)-4:],
	}
	// 判断邀请人是否存在
	if r.StewardID != 0 { // 如果邀请人是健管师
		steward, err := HealthManagerService.GetHealthManagerInfo(r.StewardID)
		if err != nil {
			response.Result(7, "", "邀请用户不存在,请核实!", c)
			return
		}
		userData.StewardID = steward.HmId
		userData.ServiceCenterID = steward.StoreId
		userData.InviteUserID = 0
	}
	if r.InviteUserID != 0 { //如果邀请人是用户
		inviteUser, err := UserService.FindUserByID(r.InviteUserID)
		if err != nil {
			response.Result(7, "", "邀请用户不存在,请核实!", c)
			return
		}
		userData.StewardID = inviteUser.StewardID
		userData.ServiceCenterID = inviteUser.ServiceCenterID
		userData.InviteUserID = inviteUser.ID
		// 添加完成方案积分相关
		err = UserService.AddPoints(r.InviteUserID, 10, 6)
	}
	// 判断短信验证码
	key := "Sms:Phone:Code:" + r.Phone
	captcha, _ := global.GVA_REDIS.Get(context.Background(), key).Result()
	if captcha != r.Code {
		response.Result(7, "", "验证码有误,请核实!", c)
		return
	}
	err = UserService.Register(userData)
	if err != nil {
		response.FailWithDetailed("", err.Error(), c)
		return
	}
	response.Result(200, r.Phone, "注册成功", c)
}

// SignIn 登陆
func (b *BaseApi) SignIn(c *gin.Context) {
	var l userReq.Login
	err := c.ShouldBindJSON(&l)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	err = utils.Verify(l, utils.UserSignInVerify)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	u := &user.User{Phone: l.Phone, Password: l.Password}
	user, err := UserService.Login(u)
	if err != nil {
		global.GVA_LOG.Error("登陆失败! 账号不存在或者密码错误!", zap.Error(err))
		response.FailWithMessage("用户名不存在或者密码错误", c)
		return
	}
	b.TokenNext(c, *user)
	return
}

// GetAppLink 获取APP下载链接
func (b *BaseApi) GetAppLink(c *gin.Context) {
	config, err := appConfigService.GetRedisByField([]string{"app_url"})
	if err != nil {
		response.FailWithMessage("获取失败", c)
		return
	}
	response.OkWithDetailed(config["app_url"], "获取成功", c)
}

// GetBAppLink 获取APP下载链接
func (b *BaseApi) GetBAppLink(c *gin.Context) {
	config, err := appConfigService.GetRedisByField([]string{"jgs_url"})
	if err != nil {
		response.FailWithMessage("获取失败", c)
		return
	}
	response.OkWithDetailed(config["jgs_url"], "获取成功", c)
}

// TokenNext 签发jwt
func (b *BaseApi) TokenNext(c *gin.Context, user user.User) {
	j := &utils.JWT{SigningKey: []byte(global.GVA_CONFIG.JWT.SigningKey)} // 唯一签名
	claims := j.CreateClaims(request.BaseClaims{
		UUID:        user.UUID,
		ID:          user.ID,
		NickName:    user.Name,  // 这里可以设置昵称(随意)
		Username:    user.Phone, // 这里可以设置用户名(随意)
		AuthorityId: 6666,       // 这里可以随便定义一个
	})
	token, err := j.CreateToken(claims)
	if err != nil {
		global.GVA_LOG.Error("获取token失败!", zap.Error(err))
		response.FailWithMessage("获取token失败", c)
		return
	}
	// 是否多点登陆
	if !global.GVA_CONFIG.System.UseMultipoint {
		response.Result(200,
			userRes.LoginResponse{
				ID:              user.ID,
				ServiceCenterID: user.ServiceCenterID,
				StewardID:       user.StewardID,
				InviteUserID:    user.InviteUserID,
				Name:            user.Name,
				Avatar:          user.Avatar,
				Types:           user.Types,
				Token:           token,
				ExpiresAt:       claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
			}, "登录成功", c)
		return
	}
	// 获取jwt缓存
	if jwtStr, err := jwtService.GetRedisJWT("C:SignInToken:" + strconv.FormatUint(uint64(user.ID), 10)); err == redis.Nil {
		if err := jwtService.SetRedisJWT(token, "C:SignInToken:"+strconv.FormatUint(uint64(user.ID), 10)); err != nil {
			global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
			response.FailWithMessage("设置登录状态失败", c)
			return
		}
		response.OkWithDetailed(userRes.LoginResponse{
			ID:              user.ID,
			ServiceCenterID: user.ServiceCenterID,
			StewardID:       user.StewardID,
			InviteUserID:    user.InviteUserID,
			Name:            user.Name,
			Avatar:          user.Avatar,
			Types:           user.Types,
			Token:           token,
			ExpiresAt:       claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
		}, "登录成功", c)
	} else if err != nil {
		global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
		response.FailWithMessage("设置登录状态失败", c)
	} else {
		var blackJWT system.JwtBlacklist
		blackJWT.Jwt = jwtStr
		if err := jwtService.JsonInBlacklist(blackJWT); err != nil {
			response.FailWithMessage("jwt作废失败", c)
			return
		}
		if err := jwtService.SetRedisJWT(token, "C:SignInToken:"+strconv.FormatUint(uint64(user.ID), 10)); err != nil {
			response.FailWithMessage("设置登录状态失败", c)
			return
		}
		response.Result(200,
			userRes.LoginResponse{
				ID:              user.ID,
				ServiceCenterID: user.ServiceCenterID,
				StewardID:       user.StewardID,
				InviteUserID:    user.InviteUserID,
				Name:            user.Name,
				Avatar:          user.Avatar,
				Types:           user.Types,
				Token:           token,
				ExpiresAt:       claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
			}, "登录成功", c)
	}
}

// ForgetPassword 忘记密码
// @Tags User
// @Summary 用户修改密码
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data query user.User true "用id查询用户"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
// @Router /api/base/forgetPassword [post]
func (b *BaseApi) ForgetPassword(c *gin.Context) {
	var uf userReq.ForgetPassword
	err := c.ShouldBindJSON(&uf)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	//userInfo := &userReq.ForgetPassword{Phone: uf.Phone}
	//user, err := UserService.CodeLogin(userInfo)
	user, _ := UserService.FindUserByWhere(map[string]interface{}{"phone": uf.Phone}, "*")
	if user.ID == 0 {
		response.FailWithMessage("该账号不存在,请注册!", c)
		return
	}
	key := "Sms:Phone:Code:" + uf.Phone
	captcha, _ := global.GVA_REDIS.Get(context.Background(), key).Result()
	if captcha != uf.Code {
		response.FailWithMessage("请输入正确验证码!", c)
		return
	}
	b.TokenNext(c, *user)
	return
}
